﻿using System;
//using System.Collections.Generic;
//using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Windows.Forms;

namespace GameAnalyzer
{
    public partial class frmAnalyzer : Form
    {
        //Constants
        private readonly string ROUND = "Round";
        private readonly string AGENT = "Agent";
        private readonly string UTILITY = "Utility";
        private readonly string SUM = "Sum";
        private readonly string EXPECTED = "Expected";
        private readonly string PLAYED = "Played";
        private readonly string AVG_UTIL = "AvgUtil";
        private readonly string TOTAl_SCORE = "TotalScore";
        private readonly Color COLOR_ACTIVE_PLAYER = Color.Yellow;
        private readonly Color COLOR_ACTIVE_DECIDER = Color.LightGreen;

        private int _numOfPlayers = 0;

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="fileName">file name to analyze</param>
        public frmAnalyzer(String fileName)
        {
            InitializeComponent();

            txtFile.Text = fileName;
        }

        public frmAnalyzer()
            : this(null)
        {
        }

        /// <summary>
        /// Calculates final statistics of the game
        /// </summary>
        /// <param name="fromLine">first row to consider (from GUI table)</param>
        /// <param name="toLine">last row to consider (from GUI table)</param>
        /// <param name="numOfPlayers">total number of players</param>
        private void caculateStats(int fromLine, int toLine, int numOfPlayers)
        {
            int[] moves = new int[numOfPlayers];
            int[] expectations = new int[numOfPlayers];
            double[] score = new double[numOfPlayers];
            dgvStats.Rows.Clear();

            //Scan each row
            for (int i = fromLine; i <= toLine; ++i)
            {
                //Scan each cell
                for (int j = 0; j < numOfPlayers; ++j)
                {
                    //Check if current player is the active player of current round
                    if (dgvGame.Rows[i].Cells[AGENT + j.ToString()].Style.BackColor.Equals(COLOR_ACTIVE_PLAYER))
                    {
                        ++moves[j];

                        score[j] += Double.Parse(dgvGame.Rows[i].Cells[UTILITY].Value.ToString());
                        break;
                    }
                }
            }

            //Display calculated statistics 
            for (int i = 0; i < numOfPlayers; ++i)
            {
                int newRowIndex = dgvStats.Rows.Add();
                DataGridViewRow row = dgvStats.Rows[newRowIndex];
                row.HeaderCell.Value = AGENT + " " + i.ToString();
                row.Cells[PLAYED].Value = moves[i];
                row.Cells[TOTAl_SCORE].Value = score[i];
                row.Cells[AVG_UTIL].Value = Math.Round(score[i] / moves[i], 3);
            }
        }

        /// <summary>
        /// Display data from xml game data file
        /// </summary>
        /// <param name="xmlGameData"></param>
        private void parseData(String xmlGameData)
        {
           
            try
            {
                //Delete entire grid data
                dgvGame.Rows.Clear();
                dgvStats.Rows.Clear();
                dgvGame.Columns.Clear();
                dgvStats.Columns.Clear();

                //Delete agents' values
                foreach (Control control in tblAgents.Controls)
                    tblAgents.Controls.Remove(control);

                //Open the game file
                //reader = new System.IO.StreamReader(System.IO.File.Open(xmlGameData, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.ReadWrite));
                DataSet ds = new DataSet();
                ds.ReadXml(xmlGameData);
                //Read the type of game
                AdaptiveAgents.Games.GameType type = (AdaptiveAgents.Games.GameType)Enum.Parse(
                    typeof(AdaptiveAgents.Games.GameType), ds.Tables["GameDetails"].Rows[0][1].ToString());
                
                //Check which labels in legend to display
                switch (type)
                {
                    case AdaptiveAgents.Games.GameType.Normal:
                        lblActivePlayer.Visible = true;
                        lblActiveDecider.Visible = false;
                        break;
                    case AdaptiveAgents.Games.GameType.Cyclic:
                        lblActivePlayer.Visible = true;
                        lblActiveDecider.Visible = true;
                        break;
                }

                //Read the number of players
                int numOfPlayers = int.Parse(ds.Tables["GameDetails"].Rows[0][0].ToString()); //reader.ReadLine().Trim(','));
                _numOfPlayers = numOfPlayers;

                //Create a grid according to number of players
                createGameGrid(numOfPlayers);
                createStatsGrid(numOfPlayers);

                //Read the epsilon values
                for (int i = 0; i < numOfPlayers; ++i)
                {
                    Label lblAgent = new Label();
                    lblAgent.Text = "Agent " + i.ToString();

                    Label lblValue = new Label();
                    lblValue.Text = ds.Tables["PlayersDetails"].Rows[i]["Epsilon"].ToString();

                    LinkLabel lnkDistributon = new LinkLabel();
                    lnkDistributon.Text = ds.Tables["PlayersDetails"].Rows[i]["Distribution"].ToString();
                        //"Distribution";
                    lnkDistributon.Click += new EventHandler(lnkDistributon_Click);
                    lnkDistributon.Tag = "Dist";

                    tblAgents.Controls.Add(lblAgent);
                    tblAgents.Controls.Add(lblValue);
                    tblAgents.Controls.Add(lnkDistributon);
                }
                //Read turn data
                
                double sum = 0;
                int round = 1;
                DataTable table = ds.Tables["GameMoves"];
                int limit = table.Rows.Count;

                for (int i  = 0; i < limit; ++i)
                {
                    int newRowIndex = dgvGame.Rows.Add();
                    DataGridViewRow row = dgvGame.Rows[newRowIndex];

                    row.Cells[ROUND].Value = round++;
                    //row.HeaderCell.Value = round++;

                    //Mark active player and decider cells
                    int activePlayer = int.Parse(table.Rows[i]["ActivePlayer"].ToString());
                    int activeDecider = int.Parse(table.Rows[i]["ActiveDecider"].ToString());

                    if (type == AdaptiveAgents.Games.GameType.Cyclic)
                        row.Cells[AGENT + activeDecider.ToString()].Style.BackColor = COLOR_ACTIVE_DECIDER;

                    row.Cells[AGENT + activePlayer.ToString()].Style.BackColor = COLOR_ACTIVE_PLAYER;

                    //Performence
                    row.Cells[UTILITY].Value = table.Rows[i]["Performence"].ToString();

                    //Print sum
                    sum += double.Parse(table.Rows[i]["Performence"].ToString());
                    row.Cells[SUM].Value = sum;

                    //Print estimated and expected values
                    for (int j = 0; j < numOfPlayers; ++j)
                    {
                        row.Cells[AGENT + j.ToString()].Value = table.Rows[i]["Agent" + j].ToString();

                        if (j == activePlayer)
                            row.Cells[EXPECTED + j.ToString()].Value = false;
                        else
                        {
                            row.Cells[EXPECTED + j.ToString()].Value = 
                                table.Rows[i]["Expected" + j].ToString() == "1" ? true : false;
                        }
                    }
                }

                //Print statistics
                caculateStats(0, dgvGame.Rows.Count - 1, numOfPlayers);
            }
            catch (System.IO.IOException ex)
            {
            }
            finally
            {
               // if (reader != null)
               //     reader.Close();
            }
        }

        //old
        private void parseData111111(String fileName)
        {
            System.IO.StreamReader reader = null;
            
            try
            {
                //Delete entire grid data
                dgvGame.Rows.Clear();
                dgvStats.Rows.Clear();
                dgvGame.Columns.Clear();
                dgvStats.Columns.Clear();

                //Delete agents' values
                foreach (Control control in tblAgents.Controls)
                    tblAgents.Controls.Remove(control);

                //Open the game file
                reader = new System.IO.StreamReader(System.IO.File.Open(fileName, System.IO.FileMode.Open,System.IO.FileAccess.Read, System.IO.FileShare.ReadWrite));
                
                //Read the type of game
                AdaptiveAgents.Games.GameType type = (AdaptiveAgents.Games.GameType)Enum.Parse(
                    typeof(AdaptiveAgents.Games.GameType), reader.ReadLine().Trim(','));

                //Check which labels in legend to display
                switch (type)
                {
                    case AdaptiveAgents.Games.GameType.Normal:
                        lblActivePlayer.Visible = true;
                        lblActiveDecider.Visible = false;
                        break;
                    case AdaptiveAgents.Games.GameType.Cyclic:
                        lblActivePlayer.Visible = true;
                        lblActiveDecider.Visible = true;
                        break;
                }

                //Read the number of players
                int numOfPlayers = int.Parse(reader.ReadLine().Trim(','));
                _numOfPlayers = numOfPlayers;

                //Create a grid according to number of players
                createGameGrid(numOfPlayers);
                createStatsGrid(numOfPlayers);

                //Read the epsilon values
                for (int i = 0; i < numOfPlayers; ++i)
                {
                    Label lblAgent = new Label();
                    lblAgent.Text = "Agent " + i.ToString();

                    Label lblValue = new Label();
                    lblValue.Text = reader.ReadLine().Trim(',');

                    LinkLabel lnkDistributon = new LinkLabel();
                    lnkDistributon.Text = "Distribution";
                    lnkDistributon.Click += new EventHandler(lnkDistributon_Click);
                    lnkDistributon.Tag = "Dist";

                    tblAgents.Controls.Add(lblAgent);
                    tblAgents.Controls.Add(lblValue);
                    tblAgents.Controls.Add(lnkDistributon);
                }
                //Read turn data
                string data = null;
                double sum = 0;
                int round = 1;
                while ((data = reader.ReadLine()) != null)
                {
                    String[] parsed = data.Split(',');
                    
                    int newRowIndex = dgvGame.Rows.Add(); 
                    DataGridViewRow row = dgvGame.Rows[newRowIndex];
   
                    row.Cells[ROUND].Value = round++;
                    //row.HeaderCell.Value = round++;

                    //Mark active player and decider cells
                    int activePlayer = int.Parse(parsed[0]);
                    int activeDecider = int.Parse(parsed[3]);
                    
                    if (type == AdaptiveAgents.Games.GameType.Cyclic)
                        row.Cells[AGENT + activeDecider.ToString()].Style.BackColor = COLOR_ACTIVE_DECIDER;

                    row.Cells[AGENT + activePlayer.ToString()].Style.BackColor = COLOR_ACTIVE_PLAYER;

                    //Performence
                    row.Cells[UTILITY].Value = parsed[1];
                    
                    //Print sum
                    sum += double.Parse(parsed[1]);
                    row.Cells[SUM].Value = sum;

                    //Print estimated and expected values
                    for (int i = 0; i < numOfPlayers; ++i)
                    {
                        row.Cells[AGENT + i.ToString()].Value = parsed[4 + 2*i];

                        if (i == activePlayer)
                            row.Cells[EXPECTED + i.ToString()].Value = false;
                        else
                            row.Cells[EXPECTED + i.ToString()].Value = parsed[4 + 2*i + 1];
                    }
                }

                //Print statistics
                caculateStats(0, dgvGame.Rows.Count - 1, numOfPlayers);
            }
            catch (System.IO.IOException ex)
            {
            }
            finally
            {
                if (reader != null)
                    reader.Close();
            }
        }

        //test
        void lnkDistributon_Click(object sender, EventArgs e)
        {
            String tag = ((LinkLabel)sender).Tag.ToString();
            if (tag.Equals("dist0"))
            {
                double[] xx = { 0, 0.1, 0.2, 0.4, 0.9, 1 };
                double[] yy = { 0.3, 0.2, 0.05, 0.45, 0.7, 0.7 };

                frmDistribution frmDist = new frmDistribution();
                frmDist.Text = "Agent 0";
                frmDist.createStepGraph("Mean = value", xx, yy);

                frmDist.ShowDialog();
            }
        }

        /// <summary>
        /// Creates the statistics grid
        /// </summary>
        /// <param name="numOfPlayers">total number of players</param>
        private void createStatsGrid(int numOfPlayers)
        {
            dgvStats.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders;

            //Create Agent column
            DataGridViewTextBoxColumn clnAgent = new DataGridViewTextBoxColumn();
            clnAgent.DataPropertyName = AGENT;
            clnAgent.HeaderText = "Agent";
            clnAgent.Name = AGENT;
            clnAgent.ReadOnly = true;
            //dgvStats.Columns.Add(clnAgent);
          

            //Create Played column
            DataGridViewTextBoxColumn clnPlayed = new DataGridViewTextBoxColumn();
            clnPlayed.DataPropertyName = PLAYED;
            clnPlayed.HeaderText = "Played";
            clnPlayed.Name = PLAYED;
            clnPlayed.ReadOnly = true;
            dgvStats.Columns.Add(clnPlayed);

            //Create Average Utility column
            DataGridViewTextBoxColumn clnAvgUtility = new DataGridViewTextBoxColumn();
            clnAvgUtility.DataPropertyName = AVG_UTIL;
            clnAvgUtility.HeaderText = "Avg Utility";
            clnAvgUtility.Name = AVG_UTIL;
            clnAvgUtility.ReadOnly = true;
            dgvStats.Columns.Add(clnAvgUtility);

            //Create Total Score column
            DataGridViewTextBoxColumn clnTotalScore = new DataGridViewTextBoxColumn();
            clnTotalScore.DataPropertyName = TOTAl_SCORE;
            clnTotalScore.HeaderText = "Total Score";
            clnTotalScore.Name = TOTAl_SCORE;
            clnTotalScore.ReadOnly = true;
            dgvStats.Columns.Add(clnTotalScore);
        }

        /// <summary>
        /// Creates the game history grid
        /// </summary>
        /// <param name="numOfAgents">total number of players</param>
        private void createGameGrid(int numOfAgents)
        {
            //Create Round column
            DataGridViewTextBoxColumn clnRound = new DataGridViewTextBoxColumn();
            clnRound.HeaderText = "Round";
            clnRound.Name = ROUND;
            clnRound.ReadOnly = true;
            clnRound.SortMode = DataGridViewColumnSortMode.NotSortable;
            clnRound.AutoSizeMode = DataGridViewAutoSizeColumnMode.DisplayedCells;
            dgvGame.Columns.Add(clnRound);

            //Create AGENTS' estimate competence columns
            for (int i = 0; i < numOfAgents; ++i)
            {
                DataGridViewCellStyle style = new DataGridViewCellStyle();
                style.WrapMode = DataGridViewTriState.True;
                DataGridViewTextBoxColumn clnAgent = new DataGridViewTextBoxColumn();
                
                clnAgent.HeaderText = "Agent" + i.ToString();
                clnAgent.Name = AGENT + i.ToString();
                clnAgent.ReadOnly = true;
                clnAgent.DefaultCellStyle = style;
                clnAgent.SortMode = DataGridViewColumnSortMode.NotSortable;
                clnAgent.AutoSizeMode = DataGridViewAutoSizeColumnMode.DisplayedCells;
                dgvGame.Columns.Add(clnAgent);
            }

            //Create Utility column
            DataGridViewTextBoxColumn clnUtility = new DataGridViewTextBoxColumn();
            //clnUtility.DataPropertyName = UTILITY;
            clnUtility.HeaderText = "Performence";
            clnUtility.Name = UTILITY;
            clnUtility.ReadOnly = true;
            clnUtility.SortMode = DataGridViewColumnSortMode.NotSortable;
            clnUtility.AutoSizeMode = DataGridViewAutoSizeColumnMode.DisplayedCells;
            dgvGame.Columns.Add(clnUtility);

            //Create Sum column
            DataGridViewTextBoxColumn clnSum = new DataGridViewTextBoxColumn();
            clnSum.HeaderText = "Sum";
            clnSum.Name = SUM;
            clnSum.ReadOnly = true;
            clnSum.SortMode = DataGridViewColumnSortMode.NotSortable;
            clnSum.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
            dgvGame.Columns.Add(clnSum);

            //Create AGENTS' acting as expected columns
            for (int i = 0; i < numOfAgents; ++i)
            {
                DataGridViewCellStyle style = new DataGridViewCellStyle();
                style.Alignment = DataGridViewContentAlignment.MiddleCenter;
                DataGridViewCheckBoxColumn clnExpected = new DataGridViewCheckBoxColumn();
                clnExpected.HeaderText = "Expected" + i.ToString();
                clnExpected.Name = EXPECTED + i.ToString();
                clnExpected.ReadOnly = true;
                
                
                clnExpected.DefaultCellStyle = style;
                clnExpected.SortMode = DataGridViewColumnSortMode.NotSortable;
                clnExpected.AutoSizeMode = DataGridViewAutoSizeColumnMode.DisplayedCells;
                dgvGame.Columns.Add(clnExpected);
            }
        }

        private void frmAnalyzer_Load(object sender, EventArgs e)
        {
            lblActivePlayer.BackColor = COLOR_ACTIVE_PLAYER;
            lblActiveDecider.BackColor = COLOR_ACTIVE_DECIDER;

            //Get the data from game file
            dgvStats.DataMember = "Game";
            //dgvGame.DataSource = createGameTable(); //TODO delete 
            tblAgents.HorizontalScroll.Enabled = false;
            tblAgents.HorizontalScroll.Visible = false;
            
            //dgvGame[1, 0].Value = "bla" + EnvironmentType.NewLine + "5";

            if (txtFile.Text.Length > 0)
                parseData(txtFile.Text);

            //createStatsGrid();
            //dgvStats.DataSource = createStatsTable();
        }

        private void btnBrowse_Click(object sender, EventArgs e)
        {
            if (opfOpenLogFile.ShowDialog() == DialogResult.OK)
            {
                txtFile.Text = opfOpenLogFile.FileName;
                parseData(txtFile.Text);
            }
        }

        private void lnkDist_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            String tag = ((LinkLabel)sender).Tag.ToString();
            if (tag.Equals("dist0"))
            {
                double[] xx = { 0, 0.1, 0.2, 0.4, 0.9, 1};
                double[] yy = { 0.3, 0.2, 0.05, 0.45, 0.7, 0.7 };

                frmDistribution frmDist = new frmDistribution();
                frmDist.Text = "Agent 0";        
                frmDist.createStepGraph("Mean = value",xx, yy);
                
                frmDist.ShowDialog();
            }
        }

        private void dgvGame_SelectionChanged(object sender, EventArgs e)
        {
            if (dgvGame.SelectedRows.Count == 0)
                return;

            int toLine = dgvGame.SelectedRows[0].Index;
            int fromLine = dgvGame.SelectedRows[dgvGame.SelectedRows.Count - 1].Index;

            caculateStats(fromLine, toLine, _numOfPlayers);
        }

    }
}
